package com.block.datapush.special.api;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.block.common.enums.ProfitSharingEnum;
import com.block.common.model.dto.ThirdInfoDTO;
import com.block.common.service.IApplicationInfoService;
import com.block.common.service.LogFactory;
import com.block.common.service.merchant.IMerchantThirdBaseInfoService;
import com.block.datapush.model.result.ApiPushResult;
import com.block.datapush.special.enums.OrderStatusEnum;
import com.block.db.entity.*;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 下游全流程
 *
 */
@Service
public class CommonAPISPushService implements IApiPushService {

    private static final Logger log = LogFactory.getPushLog();

    @Autowired
    IMerchantThirdBaseInfoService merchantThirdBaseInfoService;

    @Autowired
    IApplicationInfoService applicationInfoService;

    @Value("${testMock.checkOrRegister:false}")
    private Boolean testMockCheckOrRegister;

    @Override
    public ApiPushResult matchUser(String orderNo, SpecialCostomInfo costomInfo, MemberExtInfo memberExtInfo, JSONObject jsonObject) throws Exception {

        ApiPushResult apiPushResult = new ApiPushResult();
        apiPushResult.setSuccess(false);

        String queryUrl = costomInfo.getApiMatchUrl();
        String apiSecret = costomInfo.getApiSecret();
        String apiCode = costomInfo.getApiCode();

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("mobileMd5", memberExtInfo.getMobileMd5().toLowerCase());
        paramMap.put("realName", memberExtInfo.getUsername());
        if (memberExtInfo.getSex() == 1){
            paramMap.put("sex", 1);
        }else {
            paramMap.put("sex", 2);
        }
        paramMap.put("age",memberExtInfo.getAge());
        paramMap.put("province",memberExtInfo.getProvince());
        paramMap.put("provinceCode",memberExtInfo.getProvinceCode());
        paramMap.put("city",memberExtInfo.getCity());
        paramMap.put("cityCode",memberExtInfo.getCityCode());

        paramMap.put("loanAmount",memberExtInfo.getLoanAmount());
        paramMap.put("loanTime",memberExtInfo.getLoanTime());

        paramMap.put("house",memberExtInfo.getHouse());
        paramMap.put("car",memberExtInfo.getCar());
        paramMap.put("gjj",memberExtInfo.getGjj());
        paramMap.put("shebao",memberExtInfo.getShebao());
        paramMap.put("baoxian",memberExtInfo.getBaodan());
        paramMap.put("zhimaSource",memberExtInfo.getZhimaScore());
        paramMap.put("salary",memberExtInfo.getSalary());
        paramMap.put("xueli",memberExtInfo.getXueli());
        paramMap.put("yongtu",memberExtInfo.getPurpose());
        paramMap.put("yuqi",memberExtInfo.getYuqi());
        paramMap.put("gongzuo",memberExtInfo.getJob());
        paramMap.put("enterpriseOwner",memberExtInfo.getEnterpriseOwner());

        paramMap.put("huabei",memberExtInfo.getHuabei());
        paramMap.put("baitiao",memberExtInfo.getBaitiao());

        paramMap.put("outOrderNo", orderNo);
        paramMap.put("userIp", memberExtInfo.getReqIp());

        //加密
        String encrypt =  SecureUtil.aes(apiSecret.getBytes()).encryptBase64(JSON.toJSONString(paramMap));

        Map<String, Object> bizMap = new HashMap<>();
        bizMap.put("requestNo", UUID.randomUUID().toString());
        bizMap.put("appCode",apiCode);
        bizMap.put("tranData",encrypt);
        String result = null;
        // TODO test mock 240828
        if (testMockCheckOrRegister && "绍兴市".equals(memberExtInfo.getCity())) {
            result = "{\"respMsg\":\"撞库成功\",\"requestNo\":\"0000000010001001000\",\"respCode\":\"200\",\"respData\":{\"orderNo\":\"1740458423875653600\",\"outOrderNo\":\"1740458423875653600\",\"productId\":\"123456\",\"productName\":\"测试产品\",\"companyName\":\"花花呗\",\"companyLogo\":\"https://jyhdd.oss-cn-shanghai.aliyuncs.com/prodlogo/prodlogo_1724688086761337853082eae4c2f8fc365dcaf3a7e91.pic.jpg\",\"businessInfo\":\"信用贷款\",\"price\":8.01,\"protocalList\":[{\"protocalName\":\"商户的机构协议名称1\",\"protocalUrl\":\"商户的机构协议地址1\"},{\"protocalName\":\"商户的机构协议名称2\",\"protocalUrl\":\"商户的机构协议地址2\"}]}}";
        } else {
            log.info("【全流程导量】 撞库开始【infoId】{}【infoName】{}【queryUrl】{}【paramMap】{}【bizMap】{}",
                    costomInfo.getId(), costomInfo.getName(), queryUrl, JSON.toJSONString(paramMap), JSON.toJSONString(bizMap));
            result = HttpUtil.createPost(queryUrl)
                    .header("Content-Type", "application/json")
                    .timeout(3000)
                    .body(JSON.toJSONString(bizMap))
                    .execute().body();
            log.info("【全流程导量】撞库结束【infoId】{}【infoName】{}【result】{}",
                    costomInfo.getId(), costomInfo.getName(), result);
        }
        JSONObject resultObject = JSON.parseObject(result);
        String respCode = resultObject.getString("respCode");
        String respMsg = resultObject.getString("respMsg");


        apiPushResult.setBizParam(JSON.toJSONString(paramMap));
        apiPushResult.setResult(result);
        apiPushResult.setCode(respCode);
        apiPushResult.setMessage(respMsg);

        if (!StrUtil.equals(respCode, "200")) {
            return apiPushResult;
        }
        // 撞库成功之后，商户的机构数据存储
        JSONObject respData = resultObject.getJSONObject("respData");

        ThirdInfoDTO thirdInfoDTO = new ThirdInfoDTO();
        thirdInfoDTO.setInfoId(costomInfo.getId().intValue());
        thirdInfoDTO.setInfoName(costomInfo.getName());
        thirdInfoDTO.setOrderNo(orderNo);
        thirdInfoDTO.setInfoObject(respData);

        //进行分润操作
        String priceType = costomInfo.getPriceType();
        BigDecimal typeRate = costomInfo.getTypeRate();

        if (ProfitSharingEnum.PROFITPRICE.getValue().equals(priceType)) {
            BigDecimal price = respData.getBigDecimal("price"); //下游返回分润前价格
            if (price == null || price.compareTo(new BigDecimal(0.00)) == -1) {
                return apiPushResult;
            }
            BigDecimal priceRight = typeRate.multiply(price);//分润后价格
            apiPushResult.setPrice(price);
            apiPushResult.setPriceRight(priceRight);
        }
        boolean save = merchantThirdBaseInfoService.saveThirdInfo(thirdInfoDTO);
        apiPushResult.setSuccess(true);
        if (!save) {
            apiPushResult.setMessage("撞库成功，保存撞库返回数据失败");
        }
        return apiPushResult;
    }

    @Override
    public ApiPushResult register(String orderNo, SpecialCostomInfo costomInfo, MemberExtInfo memberExtInfo, JSONObject jsonObject) throws Exception {

        ApiPushResult apiPushResult = new ApiPushResult();
        apiPushResult.setSuccess(false);
        apiPushResult.setOrderNo(orderNo);

        String requestUrl = costomInfo.getApiRegisterUrl();
        String apiSecret = costomInfo.getApiSecret();
        String apiCode = costomInfo.getApiCode();

        JSONObject bizMap = new JSONObject();
        bizMap.put("mobile", memberExtInfo.getMobile());
        bizMap.put("realName", memberExtInfo.getUsername());
        if (memberExtInfo.getSex() == 1){
            bizMap.put("sex", 1);
        }else {
            bizMap.put("sex", 2);
        }
        bizMap.put("age",memberExtInfo.getAge());
        bizMap.put("province",memberExtInfo.getProvince());
        bizMap.put("provinceCode",memberExtInfo.getProvinceCode());
        bizMap.put("city",memberExtInfo.getCity());
        bizMap.put("cityCode",memberExtInfo.getCityCode());
        bizMap.put("loanAmount",memberExtInfo.getLoanAmount());
        bizMap.put("loanTime",memberExtInfo.getLoanTime());
        bizMap.put("house",memberExtInfo.getHouse());
        bizMap.put("car",memberExtInfo.getCar());
        bizMap.put("gjj",memberExtInfo.getGjj());
        bizMap.put("shebao",memberExtInfo.getShebao());
        bizMap.put("baoxian",memberExtInfo.getBaodan());
        bizMap.put("zhimaSource",memberExtInfo.getZhimaScore());
        bizMap.put("salary",memberExtInfo.getSalary());
        bizMap.put("xueli",memberExtInfo.getXueli());
        bizMap.put("yongtu",memberExtInfo.getPurpose());
        bizMap.put("yuqi",memberExtInfo.getYuqi());
        bizMap.put("gongzuo",memberExtInfo.getJob());
        bizMap.put("enterpriseOwner",memberExtInfo.getEnterpriseOwner());

        bizMap.put("huabei",memberExtInfo.getHuabei());
        bizMap.put("baitiao",memberExtInfo.getBaitiao());

        bizMap.put("outOrderNo",orderNo);
        bizMap.put("userIp",memberExtInfo.getReqIp());

        MerchantThirdBaseInfo merchantThirdBaseInfo = merchantThirdBaseInfoService.selectEntityByOrderNo(orderNo);
        if (ObjectUtil.isEmpty(merchantThirdBaseInfo)){
            apiPushResult.setMessage("商户机构数据为空【pushId】" + orderNo);
            return apiPushResult;
        }
        bizMap.put("orderNo",merchantThirdBaseInfo.getOutOrderNo());
        bizMap.put("productId",merchantThirdBaseInfo.getProductId());

        String orderId = jsonObject.getString("orderId");
        ApplicationInfo appInfoByAppCode = applicationInfoService.getAppInfoByType(StrUtil.isBlank(memberExtInfo.getAppType()) ? "jinyaohua" : memberExtInfo.getAppType());

        String protocolUrl = StrUtil.format("{}/page/user/newprotocol/{}.html", appInfoByAppCode.getApiUrl(), orderId);
        bizMap.put("protocolUrl", protocolUrl);

        //加密
        String encrypt = encrypt(JSON.toJSONString(bizMap), apiSecret);

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("requestNo", UUID.randomUUID().toString());//请求序列号
        paramMap.put("appCode",apiCode);//应用编号
        paramMap.put("tranData",encrypt);//业务参数

        String result = null;
        // TODO test mock 240828
        if (testMockCheckOrRegister && "绍兴市".equals(memberExtInfo.getCity())) {
            result = "{\"respMsg\":\"撞库成功\",\"requestNo\":\"\",\"respCode\":\"200\",\"respData\":{\"orderNo\":\"000000200000200020202\",\"message\":\"推送成功\",\"status\":\"000\"}}";
        } else {
            log.info("【全流程导量】导单开始【infoId】{}【infoName】{}【queryUrl】{}【bizMap】{}【paramMap】{}",
                    costomInfo.getId(), costomInfo.getName(), requestUrl, JSON.toJSONString(bizMap), JSON.toJSONString(paramMap));
            result = HttpUtil.createPost(requestUrl)
                    .header("Content-Type", "application/json")
                    .timeout(4000)
                    .body(JSON.toJSONString(paramMap))
                    .execute().body();
            log.info("【全流程导量】导单结束【infoId】{}【infoName】{}【result】{}",
                    costomInfo.getId(), costomInfo.getName(), result);
        }

        JSONObject resultObject = JSON.parseObject(result);
        String respCode = resultObject.getString("respCode");
        String respMsg = resultObject.getString("respMsg");

        apiPushResult.setResult(result);
        apiPushResult.setCode(String.valueOf(respCode));
        apiPushResult.setMessage(respMsg);
        apiPushResult.setBizParam(JSON.toJSONString(bizMap));

        ThirdInfoDTO thirdInfoDTO = new ThirdInfoDTO();
        thirdInfoDTO.setOrderNo(orderNo );
        thirdInfoDTO.setRetCode(respCode );
        thirdInfoDTO.setRetMsg(respMsg);
        thirdInfoDTO.setResultInfo(result);
        thirdInfoDTO.setStatus("FAILED");

        if (StrUtil.equals(String.valueOf(respCode), "200")) {
            JSONObject respData = resultObject.getJSONObject("respData");
            String status = respData.getString("status");
            String message = respData.getString("message");
            thirdInfoDTO.setRetCode(respCode+"|"+status );
            thirdInfoDTO.setRetMsg(respMsg+"|"+message);
            if(StrUtil.equals(String.valueOf(status), "000")){
                thirdInfoDTO.setStatus("SUCCESS");
            }
        }
        merchantThirdBaseInfoService.updateThirdInfo(thirdInfoDTO);

        if (StrUtil.equals(String.valueOf(respCode), "200")) {
            JSONObject respData = resultObject.getJSONObject("respData");
            String status = respData.getString("status");
            String message = respData.getString("message");
            apiPushResult.setCode(respCode+"|"+status);
            apiPushResult.setMessage(respMsg+"|"+message);
            if (StrUtil.equals(String.valueOf(status), "000")){
                //修改时间
                apiPushResult.setSuccess(true);
                apiPushResult.setSettleFlag(true);
                apiPushResult.setStatus(OrderStatusEnum.SUCCESS.getValue());
                return apiPushResult;
            }
        }
        apiPushResult.setSuccess(false);
        apiPushResult.setSettleFlag(false);
        apiPushResult.setStatus(OrderStatusEnum.FAILED.getValue());
        return apiPushResult;
    }

    @Override
    public ApiPushResult queryResult(SpecialCostomInfo costomInfo, SpecialDataApiInfo dataApiInfo, JSONObject jsonObject) {
        return null;
    }

    public static String encrypt(String sSrc, String sKey) {
        if (sKey == null) {
            System.out.print("Key 为空 null");
            return null;
        }// 判断 Key 是否为 16 位
        if (sKey.length() != 16) {
            if(sKey.length()!=32){
                System.out.print("Key 不合法");
                return null;
            }
        }
        try {
            byte[] raw = sKey.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); // "算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); // 此处使用 BASE64 做转码功能，同时能起到 2 次加密的作用。
            return Base64.encodeBase64String(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
}
